-module(biz_vendor).
-include("rec_dec.hrl").
-behaviour(gen_server).
-export([start/0,init/1,handle_call/3,handle_cast/2,handle_info/2,terminate/2,code_change/3]).

-define(SERVER    , ?MODULE).

start()  ->
	case gen_server:start({local, ?SERVER}, ?MODULE, [], []) of 
	{ok,_} ->
		gen_server:call(?SERVER,refresh),
		ok;
	{error,{already_started,Pid}} ->
		gen_server:call(Pid,refresh);
	{error,Reason} ->
		%%stop(),
		io:format("start ~s service failure with ~p~n",[?SERVER,Reason])
	end.

init(_) ->
	io:format("Pid for biz_queue:~p~n",[self()]),
	process_flag(trap_exit,true),
	Vendors = 	lists:map(fun(E) ->
								{E#vendor_rec.id,E,undefined}
							end,
				vendor_service:get()),
	{ok,Vendors}.
	
handle_call(refresh,_,State) ->
	NewState = lists:map(
		fun(V) ->
			case V of
			{Id,E,undefined} ->
				{Id,E,start_vendor(E)};
			{Id,E,Pid} ->
				{Id,E,check_vendor(E,Pid)}
			end
		end,
		State
	),
	{reply, ok,NewState};
	
handle_call(stop,_,State) ->
	gen_server:call(self(),stop_inst),
	{stop,"By request",ok,State};
	
handle_call({add,V},_,State) when is_record(V,vendor_rec) ->
	{reply,ok,State ++ [{V#vendor_rec.id,V,start_vendor(V)}]};
	
%% reset the Vendor Serivce for specified Vendor_Id

handle_call({reset_inst,Vendor_Id},_,State) ->
	io:format("reset the vendor:~p~n",[Vendor_Id]),
	{
		reply,
		case lists:keyfind(Vendor_Id,1,State) of
		{Vendor_Id,_,Pid} ->
			gen_server:call(Pid,reset);
		_ ->
			gen_server:call(self(),refresh)
		end,
		State
	};
handle_call(stop_inst,_,State) ->
	{reply,
		ok,
		lists:map(
			fun(V) ->
				case V of
				{Id,E,undefined} ->
					V;
				{Id,E,Pid} ->
					gen_server:call(Pid,stop),
					{Id,E,undefined}
				end
			end,
			State
		)};
handle_call(dump,_,State) ->
	io:format("dump biz_vendor ~p~n",[State]),
	{reply,ok,State};

handle_call({vendor,Vendor_Id,Request},_,Vendors) ->
	{reply,
		case lists:keyfind(Vendor_Id,1,Vendors) of
		false ->
			{error,"No Vendor Info found"};
		{Vendor_Id,A,undefined} ->
			io:format("Vendor ~p does not start~n",[A]),
			{error,"Vendor is not activated"};
		{Vendor_Id,_,Pid} ->
			gen_server:call(Pid,Request)
		end,
		Vendors};
handle_call({"",Pid,Reason},_,State) ->
	{reply,ok,State};
	
handle_call({forward_queue_msg,{Vendor_Id,Queue_Id},Msg},_,Vendors) ->
	{reply,
		case lists:keyfind(Vendor_Id,1,Vendors) of
		false ->
			{error,"no vendor found"};
		{Vendor_Id,_,undefined} ->
			{error,"vendor is not activated"};
		{Vendor_Id,_,Pid} ->
			gen_server:call(Pid,{forward_queue_msg,Queue_Id,Msg})
		end,Vendors};
handle_call({forward_vendor_msg,Id,Msg},_,Vendors) ->
	{reply,
		case lists:keyfind(Id,1,Vendors) of 
		false ->
			{error,"no vendor found"};
		{Vendor_Id,_,undefined} ->
			{error,"vendor is not activated"};
		{Vendor_Id,_,Pid} ->
			gen_server:call(Pid,Msg)
		end,Vendors};
handle_call(_,_,State) ->
	{reply, {error,"no func define", State}}.
	
handle_cast(_, State) ->
	{noreply,State}.
handle_info(_, State) ->
	{noreply,State}.
terminate(_, _) ->
	ok.
code_change(_, State, _) ->
	{ok,State}.
	
start_vendor(Vendor) when is_record(Vendor,vendor_rec) ->
	try vendor_inst:start(Vendor) of 
		Val -> Val
	catch 
		M:E ->
			io:format("catch ~p ~p ~n",[M,E]),
			error
	end.


	
check_vendor(E,Pid) ->
	case gen_server:call(Pid,ping) of
	ok ->
		Pid;
	_ ->
		undefined
	end.

	